ネットワーク・デバイスのための EPICS デバイス・サポート
EPICS 横断化グループ 小田切 淳一
- 概要
- 全体構成
- サポートされるデバイス
- リンク・フィールドの書式
- デバッグのための機能
- デバイス・サポート開発者のために
1 概要
近年の加速器制御システムでは、イーサネット経由で制御を行うデバイスが多用される傾向にあります。このようなデバイスは、メッセージ・ベースのトランザクションにより
EPICS の IOC と通信を行うことになります。このような通信は「遅い」I/O であり、
EPICS のデバイス/ドライバ・サポートは非同期で動作する必要があります。非同期式のデバイス/ドライバ・サポートは、同期式のものに比べて作りが複雑になるため、個々のデバイスのデバイス/ドライバ・サポートを別々に作成すると、その作業は膨大な量になります。また、開発後の維持の負担も大きなものになります。デバイスと送受信するメッセージの内容はデバイスに依存しますが、メッセージを送受信する仕組み自体は基本的にはデバイスに依存しないため、複雑にな低レベルのコードはデバイス間で共有し、開発の効率を上げることができます。また、共有される一つのモジュールに改善の努力を集中することで、多くのデバイスが、その恩恵を受けることができます。
現在、ネットワーク・デバイスのためのデバイス・サポートをデバイス依存層とデバイス非依存層に分けてモジュール化する作業が、
KEK EPICS 横断化グループ、
J-PARC 制御グループ、理研の重イオン・リニアック制御グループ、および(株)三菱コントロール・ソフトウェアにより行われています。間もなく、
5 機種のデバイス( 3 機種の PLC と 2 機種の組込みコントローラ)がサポートされる予定です。
2 全体構成
一つのデバイスと通信するために、以下に示す三つのモジュールを必要とします。一例として、横河社製
FA-M3 PLC の場合、かつ、モジュールをインクリメンタルに
IOC 上にロードする場合のスタートアップ・スクリプトを示すと、
cd "/where/the/modules/are/"
ld < d rvNetMpf.o
ld < devNetDev.o
ld < devYewPlc.o
のようになります。VxWorks の Linking Loader がモジュール間の外部参照を解決するために、 モジュールをロードする順序は大切ですのでご注意下さい(ホスト計算機上で静的にリンクする場合には問題になりません)。はじめの二つがデバイスに依存しないモジュールで、最後がデバイス(
FA-M3 )固有のモジュールです。以下、各モジュールについて、その機能を簡単に説明します。
drvNetMpf.o
"Mpf"は Message Passing Facility の略です。上位のモジュールから渡されたメッセージを通信相手に送り、もしレスポンスがあれば、それを受け取り、上位層に返す役割を担います。そのためのソケットの生成、送信タスク/受信タスクの生成、メッセージのバッファリング等を行います。このモジュールは、メッセージの内容には一切関知しません。
devNetDev.o
このモジュールは、EPICS
の非同期 I/O の仕組みを隠蔽し、上位層のモジュールに簡単な関数の形で提供します。また、複数のデバイスに共通して利用される機能をライブラリとして用意する場合には、このモジュールの中に置きます。このモジュールもメッセージの内容には一切関知しません。
devYewPlc.o
このモジュールは、横河社製
FA-M3 PLC に固有なプロトコル(コマンド/レスポンス体系)を実装するモジュール
です。 FA-M3 の場合に限らず、各デバイスをサポートするモジュールは、一般に、以下の三つの
関数を実装する必要があります。
- リンク・フィールド解析関数:レコードのリンク・フィールド(
INP, OUTフィールド )の解析を行い、デバイスのアドレス情報を取得します。
- コマンド生成関数
:デバイスのアドレス情報を基に、送信メッセージ(コマンド)を構築します。
- レスポンス解析関数
:受信メッセージ(レスポンス)を解析し、正常であればデータをレコードのバッファに転送します。
デバイスに固有なモジュールの機能の詳細については、次節で説明します。
3 サポートされるデバイス
現在、FA-M3 を含めた六つのデバイスをサポートするため、以下のデバイス毎のモジュール
(機種/開発者/状況)の開発が進められています。
- devYewPlc.o ( 横河 PLC /KEK/一応、完成(実機によるイベント通知機能のテストは未完
))
- devJkYewPlc.o ( 横河 PLC (「J-PARC 仕様」)/
KEK/同上)
- devOmrPlc.o ( オムロン PLC /理研/開発中
)
- devMelPlc.o ( 三菱 PLC /三菱電機/完成)
- devEmbLan.o ( KEK 開発の組込みコントローラ ( EMB-LAN100)/KEK/開発中)
- devNDim.o
( 理研開発の組込みコントローラ
( N-DIM )/理研/開発中 )
これらのモジュールは、任意の組合せで利用することができます。例えば、
cd "/where/the/modules/are/"
ld < drvNetMpf.o
ld < devNetDev.o
ld < devYewPlc.o
ld < devOmrPlc.o
ld < devMelPlc.o
とすれば、この IOC は、3機種の
PLC と通信することができます。デバイスに依存しない最初の二つのモジュールは、他の三つのデバイス毎のモジュールに共有されて利用されます。デバイス毎のモジュール相互の間ではシンボルの参照・被参照関係が存在しないため、ロードする順序に制約はありません。
3-1 横河 PLC 用デバイス・サポート
( devYewPlc.o )
横河社製 FA-M3 PLC をサポートするモジュールです。 FA-M3 の「パソコンリンクコマンド説明書」に記載されているプロトコルの他、未公開のプロトコルも併用しています。いずれもバイナリ・モードの場合のみのサポートです。
アスキー・モードでは使えませんのでご注意下さい。
(ネットワーク・プロトコル)
- デバイス・サポートのデフォルト(ハードウェアのデフォルトのことではありません)は
UDP です。TCP
を使用する場合には、スタートアップ・スクリプト中で、 iocInit
を実行する前に 、 yewPlcUseTcp
= 1という行を挿入して下さい。
(リンク・フィールドの書式)
(デバイス・タイプ)
- EPICS レコードの
DTYP フィールドには、 "Yew
Plc " と指定して下さい。
(標準的な機能)
- 10種類のレコード型をサポート(ai, ao, bi, bo,
longin, longout, mbbiDirect, mbboDirect, waveform, arrayout )。
- bi, bo はビット・デバイス1点のビット単位の読み書きに使用します。
- ai, ao, longin, longout はワード・デバイス1点のワード単位の読み書きに使用します。
- mbbiDirect, mbboDirect はビット・デバイス16点、またはワード・デバイス1点のワード単位の読み書きに使用します。
- waveform, arrayout ビット・デバイス 、またはワード・デバイスのワード単位の一括した読み書きに使用します。
- arrayout レコードは EPICS
標準のレコードではありません。入力型の
waveform レコードを出力型に書き換えたものです。基本的には waveform レコードの INP フィールドを OUT フィールドに置き換えたものとして理解して頂いて結構です。
- 分割送受信機能:配列データのサイズが、1回のトランザクションで
PLC が送受信できるバイト数を超える場合、制限に収まるようにデータを分割し、複数回に分けてトランザクション
を行います。
(特殊な機能)
- イベント通知サービス機能をサポート:
FA-M3 用の通信モジュール F3LE01-5T のイベント通知サービス機能をサポートします( 100 Mbps 対応の通信モジュール
F3LE11-0T にはこの機能はありません。ご注意下さい)。
- EPICS レコードの
DTYP フィールドには、 "Yew
Plc Event " と指定して下さい。
- EPICS レコードの SCAN フィールドに
"I/O Intr"を指定した場合にのみ、レコードがプロセスされます(イベント通知を受け取るレコードを周期的にスキャンすることには意味がありません)。
- スタートアップ・スクリプト中で、 iocInit を実行した後で 、
startEventServer というコマンド(引数なし)を実行して下さい。
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devAiYewPlc,"Yew
Plc")
device(ao,INST_IO,devAoYewPlc,"Yew Plc")
device(bi,INST_IO,devBiYewPlc,"Yew Plc")
device(bo,INST_IO,devBoYewPlc,"Yew Plc")
device(longin,INST_IO,devLiYewPlc,"Yew Plc")
device(longout,INST_IO,devLoYewPlc,"Yew Plc")
device(mbbiDirect,INST_IO,devMbbiDirectYewPlc,"Yew Plc")
device(mbboDirect,INST_IO,devMbboDirectYewPlc,"Yew Plc")
device(waveform,INST_IO,devWfYewPlc,"Yew Plc")
device(arrayout,INST_IO,devAroYewPlc,"Yew Plc")
device(ai,INST_IO,devAiYewPlcEvent,"Yew Plc
Event ")
device(ao,INST_IO,devAoYewPlcEvent,"Yew Plc Event")
device(bi,INST_IO,devBiYewPlcEvent,"Yew Plc Event")
device(bo,INST_IO,devBoYewPlcEvent,"Yew Plc Event")
device(longin,INST_IO,devLiYewPlcEvent,"Yew Plc Event")
device(longout,INST_IO,devLoYewPlcEvent,"Yew Plc Event")
device(mbbiDirect,INST_IO,devMbbiDirectYewPlcEvent,"Yew Plc Event")
device(mbboDirect,INST_IO,devMbboDirectYewPlcEvent,"Yew Plc Event")
device(waveform,INST_IO,devWfYewPlcEvent,"Yew Plc Event")
device(arrayout,INST_IO,devAroYewPlcEvent,"Yew Plc Event")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
3-2 『J-PARC 仕様』
横河 PLC 用デバイス・サポート ( devJkYewPlc.o )
同じく、横河社製 FA-M3 PLC をサポートするモジュールですが、「J-PARC ルール」(間接書き込みと
PLC ID の検査機能)を実装している点が devYewPlc.o と異なります。横河 PLC の標準デバイス・サポート( devYewPlc.o ) と同時に
IOC にロードして使用することができます。
(ネットワーク・プロトコル)
(リンク・フィールドの書式)
- devYewPlc.o に準じます。
- 実際には、データは INP フィールドに指定されたアドレスにではなく、間接書き込みのためのポートに先のアドレスとともに書き込まれます(配列データの場合はデータ数も)。書き込まれたポートからアドレスで指定された最終的な目的地にデータを転送するのは、
PLC 内のラダーの役割です。ポートへの書き込みに際して、 ラダーとの同期は、ポート内のフラグを介して行われます。
(デバイス・タイプ)
- EPICS レコードの
DTYP フィールドには、"JK Yew
Plc" と指定して下さい。イベント通知サービス機能を利用する場合は、 "JK Yew Plc Event" と指定して下さい。
(標準的な機能)
- devYewPlc.o に準じますが、アクセス可能な
PLC のデバイスの範囲については、ラダー側の実装に依存します。
(特殊な機能)
- PLC ID 検査機能:別途、plcIdList.o
モジュールが必要です。インクリメンタルにロードする場合には、このモジュールは、
devJkYewPlc.o より前にロードされる必要があります(ホスト上で単一のモジュールにリンクする場合には問題ではありません)。二重にロードすることのないようにご注意下さい(摩可不思議な現象が起こります)。
PLC ID 検査機能を使用する場合には、スタートアップ・スクリプト中で、 iocInit を実行する前に、以下に示すコマンドを実行する必要があります。
hostPlcAdd( "hostname", "192.168.210.1", 4, 0 )
"hostname": PLC のホスト名
"192.168.210.1": PLC の IP アドレス
4:
PLC ID
0:
オプション :登録しようとする ( IP-ID ) のセットと衝突する登録が既に存在する場合、 0: エラーを返して拒否、
1: 既にある登録を上書き
この例では、hostname と IP の紐付も同時に行っていますが、すでに
VxWorks の hostAdd( ) 関数でこれが行われている場合には、第一引数を 0 として下さい( "hostname" を
null とする)。
- 書き込みポート経由の書き込み:アプリケーション開発者が意識すべき事は特にありません。
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devJkAiYewPlc,"JK
Yew Plc")
device(ao,INST_IO,devJkAoYewPlc,"JK Yew Plc")
device(bi,INST_IO,devJkBiYewPlc,"JK Yew Plc")
device(bo,INST_IO,devJkBoYewPlc,"JK Yew Plc")
device(longin,INST_IO,devJkLiYewPlc,"JK Yew Plc")
device(longout,INST_IO,devJkLoYewPlc,"JK Yew Plc")
device(mbbiDirect,INST_IO,devJkMbbiDirectYewPlc,"JK Yew Plc")
device(mbboDirect,INST_IO,devJkMbboDirectYewPlc,"JK Yew Plc")
device(waveform,INST_IO,devJkWfYewPlc,"JK Yew Plc")
device(arrayout,INST_IO,devJkAroYewPlc,"JK Yew Plc")
device(ai,INST_IO,devJkAiYewPlcEvent,"JK Yew Plc Event")
device(ao,INST_IO,devJkAoYewPlcEvent,"JK Yew Plc Event")
device(bi,INST_IO,devJkBiYewPlcEvent,"JK Yew Plc Event")
device(bo,INST_IO,devJkBoYewPlcEvent,"JK Yew Plc Event")
device(longin,INST_IO,devJkLiYewPlcEvent,"JK Yew Plc Event")
device(longout,INST_IO,devJkLoYewPlcEvent,"JK Yew Plc Event")
device(mbbiDirect,INST_IO,devJkMbbiDirectYewPlcEvent,"JK Yew Plc
Event")
device(mbboDirect,INST_IO,devJkMbboDirectYewPlcEvent,"JK Yew Plc
Event")
device(waveform,INST_IO,devJkWfYewPlcEvent,"JK Yew Plc Event")
device(arrayout,INST_IO,devJkAroYewPlcEvent,"JK Yew Plc Event")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
3-3 オムロン PLC 用デバイス・サポート ( devOmrPlc.o ) [ 開発中
]
オムロン社製 PLC をサポートするモジュールです。 FINS プロトコルを使用しています。 アスキー・モードでは使えませんのでご注意下さい。
(ネットワーク・プロトコル)
- デバイス・サポートのデフォルト(ハードウェアのデフォルトのことではありません)は
UDP です。TCP
を使用する場合には、スタートアップ・スクリプト中で、 iocInit
を実行する前に 、
omrPlcUseTcp = 1という行を挿入して下さい。
(リンク・フィールドの書式)
(デバイス・タイプ)
- EPICS レコードの DTYP
フィールドには、 "Omr Plc" と指定して下さい。
(標準的な機能)
(FINS ノードアドレスの登録 )
- スタートアップ・スクリプト中で、
iocInit を実行する前に
、FINS ノードアドレスを登録する必要があります。以下に示すコマンドを実行します(形式上、「
J-PARC 仕様」の ID 検査機能の場合に似ていますが、文脈は全く異なりますのでご注意下さい)。
finsNodeAdd( "hostname", "192.168.210.1", 4, 0 )
"hostname": PLC のホスト名
"192.168.210.1": PLC の IP
4:
PLC の FINS ノード・アドレス
0:
オプション:登録しようとする ( IP-ID ) のセットと衝突する登録が既に存在する場合、0: エラーを返して拒否
、1: 既にある登録を上書き
この例では、hostname と IP の紐付も同時に行っていますが、すでに VxWorks
の hostAdd( ) 関数でこれが行われている場合には、第一引数を
0 として下さい( "hostname" を null とする)。
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devAiOmrPlc,"Omr
Plc")
device(ao,INST_IO,devAoOmrPlc,"Omr Plc")
device(bi,INST_IO,devBiOmrPlc,"Omr Plc")
device(bo,INST_IO,devBoOmrPlc,"Omr Plc")
device(longin,INST_IO,devLiOmrPlc,"Omr Plc")
device(longout,INST_IO,devLoOmrPlc,"Omr Plc")
device(mbbiDirect,INST_IO,devMbbiDirectOmrPlc,"Omr Plc")
device(mbboDirect,INST_IO,devMbboDirectOmrPlc,"Omr Plc")
device(waveform,INST_IO,devWfOmrPlc,"Omr Plc")
device(arrayout,INST_IO,devAroOmrPlc,"Omr Plc")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
3-4 三 菱 PLC 用デバイス・サポート ( devMelPlc.o )
三菱電機社製 MELSEC-Q シリーズをサポートするモジュールです。 MC ( Melsec Communication
) プロトコル、QnA 互換
3E フレーム(バイナリ・モード)を使用しています。 アスキー・モードでは使えませんのでご注意下さい。
(ネットワーク・プロトコル)
- デバイス・サポートのデフォルト(ハードウェアのデフォルトのことではありません)は
UDP です。TCP
を使用する場合には、スタートアップ・スクリプト中で、 iocInit
を実行する前に 、
melPlcUseTcp = 1という行を挿入して下さい。
(リンク・フィールドの書式)
(デバイス・タイプ)
- EPICS レコードの
DTYP フィールドには、 "Mel
Plc " と指定して下さい。
(標準的な機能)
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devAiMelPlc,"Mel
Plc")
device(ao,INST_IO,devAoMelPlc,"Mel Plc")
device(bi,INST_IO,devBiMelPlc,"Mel Plc")
device(bo,INST_IO,devBoMelPlc,"Mel Plc")
device(longin,INST_IO,devLiMelPlc,"Mel Plc")
device(longout,INST_IO,devLoMelPlc,"Mel Plc")
device(mbbiDirect,INST_IO,devMbbiDirectMelPlc,"Mel Plc")
device(mbboDirect,INST_IO,devMbboDirectMelPlc,"Mel Plc")
device(waveform,INST_IO,devWfMelPlc,"Mel Plc")
device(arrayout,INST_IO,devAroMelPlc,"Mel Plc")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
3-5 EMB-LAN100 用デバイス・サポート ( devEmbLan.o )
[ 開発中 ]
KEK で開発された組込みコントローラ(イーサネット・コントローラ・ボード)、
EMB-LAN100 をサポートするモジュールです。 コマンド/レスポンスの送受信に加えて、アテンション通知メッセージの受信をサポートします。
.
(ネットワーク・プロトコル)
- ハードウェアの仕様により、UDP
のみがサポートされます。
(リンク・フィールドの書式)
- PLC の場合の「統一ルール」(4節を参照して下さい)に準じますが、
unit と type の指定がありません。
(デバイス・タイプ)
- EPICS レコードの
DTYP フィールドには、 "Emb
Lan " と指定して下さい。
(標準的な機能)
- 8種類のレコード型をサポート(ai, ao, longin,
longout, mbbiDirect, mbboDirect, waveform, arrayout )。
- arrayout レコードは EPICS
標準のレコードではありません
。入力型の waveform レコードを出力型に書き換えたものです。基本的には
waveform レコードの INPフィールドを OUT フィールドに置き換えたものとして理解して頂いて結構です。
- 分割送受信機能:配列データのサイズが、1回のトランザクションで
EMB-LAN100 が送受信できるバイト数を超える場合、制限に収まるようにデータを分割し、複数回に分けてトランザクション
を行います。
(特殊な機能)
- 通知機能をサポート:非標準のレコード型、
attentionRecord により、アテンション通知、再起動通知メッセージの受信をサポートします。
- EPICS レコードの DTYP フィールドには、 "Emb Lan Event
" と指定して下さい。
-
EPICS レコードの SCAN フィールドに
"I/O Intr"を指定した場合にのみ、レコードがプロセスされます(イベント通知を受け取るレコードを周期的にスキャンすることには意味がありません)。
- スタートアップ・スクリプト中で、 iocInit を実行した後で 、
startEventServer というコマンド(引数なし)を実行して下さい。
- attentionRecord は、STUP フィールドが追加されていることを除けば waveformRecord と同じです。
- STUP フィールドに書き込みがなされると、デバイス・サポートの
setup_attention( ) 関数が実行されます。
- setup_attention( ) 関数は、以下のバラメータを EMB-LAN100 のレジスタに設定した後、アテンション通知をイネーブルする作業を行います(
setup_attention( ) 関数は、レコードの初期化時にも自動的に起動されます)。
- IOC の IP アドレス
- IOC の受信サーバがメッセージを待つポート番号
- EMB-LAN100 がメッセージに載せて送出すべきレジスタの先頭アドレス
- EMB-LAN100 がメッセージに載せて送出すべきレジスタの個数
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devAiEmbLan,"Emb
Lan")
device(ao,INST_IO,devAoEmbLan,"Emb Lan")
device(longin,INST_IO,devLiEmbLan,"Emb Lan")
device(longout,INST_IO,devLoEmbLan,"Emb Lan")
device(mbbiDirect,INST_IO,devMbbiDirectEmbLan,"Emb Lan")
device(mbboDirect,INST_IO,devMbboDirectEmbLan,"Emb Lan")
device(waveform,INST_IO,devWfEmbLan,"Emb Lan")
device(arrayout,INST_IO,devAroEmbLan,"Emb Lan")
device(attention,INST_IO,devAtEmbLanEvent,"Emb Lan Event")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
3-6 N-DIM 用デバイス・サポート ( devNDim.o
) [ 開発中 ]
理化学研究所で開発された組込みコントローラ(ネットワーク・デジタル
I/O モジュール)、N-DIM をサポートするモジュールです。現在、開発中のモジュールの中で、唯一、アスキーでメッセージの送受信を行います。
(ネットワーク・プロトコル)
- ハードウェアの仕様により、IOC からの基本命令の送受信には TCP が、
IOC からの基本命令の途中経過の通知にはUDP が使用されます。
(リンク・フィールドの書式)
- PLC の場合の「統一ルール」(4節を参照して下さい)に準じますが、
unit と type の指定がありません。
(デバイス・タイプ)
- EPICS レコードの
DTYP フィールドには、 "NDim
" と指定して下さい。
(標準的な機能)
- 8種類のレコード型をサポート(ai, MbbiDirect, MbboDirect,
stringin, stringout )。
- AI の読み込みには ai レコードを使用します。
- MbbiDirect / MbboDirect レコードは EPICS
標準のレコードではありません。
16 ビットの mbbiDirect / mbboDirect レコードを 32 ビットに拡張したものです。
- DI / DO の 8, 16, 32 ビット単位の読みだしの切替えは、レコードの NOBT フィールドへの指定により行います。
- 特殊命令の送信と、そのレスポンスの受信には stringin, stringout
レコードを使用します。
(特殊な機能)
- 通知機能をサポート:非標準のレコード型、
beamProfileRecord により、プロファイル・モニタからの UDP
パケットの受信をサポートします。
- EPICS レコードの DTYP フィールドには、 "NDim Event"
と指定して下さい。
-
EPICS レコードの SCAN フィールドに
"I/O Intr"を指定した場合にのみ、レコードがプロセスされます(イベント通知を受け取るレコードを周期的にスキャンすることには意味がありません)。
- スタートアップ・スクリプト中で、 iocInit を実行した後で 、
startEventServer というコマンド(引数なし)を実行して下さい。
- beamProfileRecord の仕様は、現在、検討中です。
(データベース定義ファイルの書式)
- アプリケーション開発環境の src ディレクトリに置かれる base.dbd ファイルに以下の行がない場合には、同ディレクトリにある xxxInclude.dbd ファイル(
xxx はアプリケーション開発環境作成時にユーザが自ら指定したものです)に以下の行を足して下さい。
device(ai,INST_IO,devAiNDim,"NDim
")
device(MbbiDirect,INST_IO,devMbbiDirectNDim,"NDim")
device(MbboDirect,INST_IO,devMbboDirectNDim,"NDim")
device(stringin,INST_IO,devSiNDim,"NDim")
device(stringout,INST_IO,devSoNdim,"NDim")
device(beamProfile,INST_IO,devBeamProfileNDim,"NDim Event")
- なお、以上とは別に、共通ドライバの初期化を行うために次の行も必要です。
driver(drvNetMpf)
4 リンク・フィールドの書式
基本的にリンク・フィールドの書式は、デバイス毎に定義します。
4-1 PLC の場合
PLC の場合、 PLC 内のデバイスの種類、名称等に差異はあるものの、似たようなアドレス指定方式が使われています。そこで、以下のような「統一的ルール」を採用することにしました。
"@hostname(port_num):unit#type
:address"
朱書きの部分は必須であり、他は省略可能です(省略した場合にはデフォルトの値が使われます)。
配列データの場合も、データ数はレコードの NELM フィールドから取得されるため、単一データの場合と同じです。
- hostname : "ホスト名"、もしくは
"192.168.210.1" の形で PLC (厳密にはイーサネット・インタフェース)を指定します。
- port_num : PLC が通信に使用するポート番号を指定します(省略すると、いわゆる「自動オープン・ポート」が仮定されます)。
- unit :
複数の CPU モジュールが存在する場合、その指定に使用します(省略すると 1 CPU が仮定されます)。
- type : データメモリ領域、リンク・リレーのような PLC 内部のデバイス種別を指定します。指定方式は機種に依存します。
- address : PLC 内部のデバイス内でのアドレスを指定します。
hostname 以外で用いられる数値は、0x で始まれば 16 進数、そうでなければ
10 進数と解釈されます。
- 横河社製 FA-M3 PLC
- type は、キャラクタ 1 文字です。
- type と address の間の ":
" は省略できます。
- address は、数値で指定します。
- 以下は全て正しい指定の例です。
field(INP,"@jhfacplc01#D1001")
field(INP,"@jhfacplc01#D:1001")
field(INP,"@jhfacplc01(0x3001)#D:
1001")
field(INP,"@jhfacplc01(0x3001):2#D:
1001")
- イベント通知メッセージを受け取るレコードの場合、port_num には、PLC 側のコマンド・サーバではなく、IOC 側でメッセージを受信するサーバ・タスクが使用するポート番号を指定します。
- 通信モジュール F3LE01-5T のイベント送信方法には「直接指定」と「間接指定」があります。「直接指定」の場合は、unit, type, address の指定は不要です。「直接指定」の場合は、レスポンス・データを書き込むシーケンス・デバイスの指定に unit, type, address を使用します。
- unit は、数値で指定します。
- type も、数値で指定します(マニュアルの表記は 16 進数です。0x を忘れないで下さい)。
- address は、数値で指定します。
- 以下に正しい指定の例を示します。
field(INP, "@jhfacplc02(9600):01#0x82:0001")
- 三菱電機社製 MELSEC-Q シリーズ
- type は、マニュアルに記載さている 1 文字または 2 文字のストリング、もしくは 16 進数です(0x を忘れないで下さい)。
- address は、数値で指定します。
- 以下の二つは、ともに正しい指定の例です。
field(INP,"@melsec01#D:1000")
field(INP,"@melsec01(5000)#0x9d
:1000")
4-2 PLC 以外の場合
"@hostname(port_num)#address
"
とします。
- hostname は "ホスト名"、もしくは
"192.168.210.1" の形で指定します。
- address には、読み書きするレジスタのアドレスを指定します(0x で始まれば 16 進数、そうでなければ
10 進数と解釈されます)。
- (port_num) を省略すると デバイスがデフォルトで使用する値に設定されます。
- waveform, arrayout, attention レコードの場合は先頭アドレスを指定します(読み書きするレジスタの数はレコードの
NELM フィールドから取得されるため、リンク・フィールドに指定する必要はありません)。
- アテンション通知を受け取る attention レコードの場合、port_num には、EMB-LAN100 側のコマンド・サーバではなく、IOC 側でメッセージを受信するサーバ・タスクが使用するポート番号を指定します。
"@hostname(port_num)#address"
とします。
- hostname は "ホスト名"、もしくは
"192.168.210.1" の形で指定します。
- address には、読み書きする
AI, DI / DO のアドレスを指定します(0x で始まれば 16 進数、そうでなければ
10 進数と解釈されます)。特殊命令の場合、address
は、コマンド・テーブルへのインデックスとして解釈されます。
- (port_num) を省略するとデバイスがデフォルトで使用する値に設定されます。
- MbbiDirect / MbboDirect レコードの場合は先頭アドレスを指定します(読み書きするチャネルの数はレコードの
NOBT フィールドから取得されるため、リンク・フィールドに指定する必要はありません)。
- プロファイル・モニタからの UDP パケットを受信する beamProfile
レコードの場合、port_num には、N-DIM 側のコマンド・サーバではなく、
IOC 側でメッセージを受信するサーバ・タスクが使用するポート番号を指定します。
5 デバッグのための機能
実行時のデバッグに使用する以下のコマンドについて説明します。
- peerShowAll
- peerShow
- showMsg
- stopMsg
- serverShowAll
- serverShow
- showServerMsg
- stopServerMsg
これらのコマンドは、
VxWorks のターミナル上で、シェル・プロンプト( -> )にタイプして使用します。
5-1 peerShowAll
Msessage Passing Facility (MPF) は、通信相手となるデバイス(より正確にはデバイス上のサーバ)に対応して、一つの
peer 構造体を生成し、相手との通信に使用される情報を格納します。
peerShowAll コマンドは、IOC 上に生成された全ての peer 構造体の ID と、そのメモリ上のアドレスをプリントします。
-> peerShowAll
Peer: 0 (0x01d758d8)
value = 0 = 0x0
これは、通信相手が一つの場合の実行結果です。 ID が 0
の peer 構造体が、メモリ・アドレス 0x01d758d8
に割り当てられてられています。
5-2 peerShow
peerShow コマンドは、引数に指定されたに生成された
ID を持つ
peer 構造体の 内容をプリントします。
-> peerShow 0
------------------------------
id:
0
protocol:
UDP
socket_fd:
14
addrss_family: 0x0002
intenet_addr: 192.168.210.131
port_number: 0x3001
in_transaction: 0
num_requests: 0
reqQ_mutex_sem_id: 0x01d3e420
req_queued_sem_id: 0x01d3e3f8
next_cycle_sem_id: 0x01d3e3d0
watchdog_id: 0x01d3e3a8
send_task_id: 0x01d756c0
recv_task_id: 0x01d72d98
send_msg_len: 0
recv_msg_len: -12
send_buf:
0x01d7591c
recv_buff_addr: 0x01d7691c
value = 0 = 0x0
5-3 showMsg
showMsg コマンドは、引数に指定されたに生成された
ID を持つ通信相手(
peer )との間で送受信されるメッセージを表示するために使用します。
->
showMsg 0
value = 0 = 0x0
=> 71 01 00 0E
26 09 00 0A 00 02 00 01 00 04 00 00 0B BC
<= F1 00 00 08 26 09 00 04 00 00 00 0E
先頭の記号 =>" は、 IOC
からデバイスに送られたコマンドが続くことを示し、
"<=" はデバイスから IOC に返されたレスポンスが続くことを示します。showMsg
コマンドの、第二引数に 1 を指定することで、アスキー文字列としてメッセージを表示させることもできます。
stopMsg コマンドにより、このメッセージを停止させることができます。引数には、
showMsg コマンドに与えた ID
を指定します。
-> stopMsg 0
5-4 イベント通知型の場合のコマンド
イベント通知型の場合についても、上で述べたコマンドに対応するものとして、
- serverShowAll
- serverShow
- showServerMsg
- stopServerMsg
が用意されています。使い方は、上に述べた対応するコマンドに準じています。
6デバイス・サポート開発者のために
ここでは、デバイス・サポートを新規に作成する開発者のために有用と思われる情報を提供します。全体の概要を示すことが目的であり、完全な詳細情報を提供するものではありません。関数や引数の型、インクルード・ファイル、マクロ定義などの詳細については、既存のデバイス/ドライバ・サポートのソース・コードを参照して下さい。
6-1 重要なデータ構造体
デバイス/ドライバ・サポートの中で使用されるデータ構造体として、以下の三つがあります。
- PEER 構造体 (イベント通知型の場合は SERVER構造体)
- 通信相手となるサーバ(イベント通知型の場合はクライアント)につき、一つの構造体が割り当てられます。
- デバイスに依存しない共通ドライバの中で定義されます。
- 通信相手メッセージの送受信に必要な仕組みの状態情報を保持します。
- TRANSACTION 構造体
- データベース・レコードのインスタンスにつき、一つの構造体が割り当てられます。
- レコードの DPVT フィールドに、この構造体へのポインタがセットされます。
- デバイスに依存しない共通ドライバの中で定義されます。
- レコードのプロセスに伴うメッセージの送受信に関わる情報を保持します。
- DEVICE 構造体
- データベース・レコードのインスタンスにつき、一つの構造体が割り当てられます。
- TRANSACTION 構造体のメンバに、この構造体へのポインタがセットされます。
- デバイス毎のデバイス・サポートの中で自由に型を定義できます。
- ハードウェア・アドレス情報などを保持するために使用します。
6-2 タスク構成と動作の概要
「2 全体構成」で述べた以下の三つの関数が、いつ、どのようなタスクのコンテキストから実行されるかに焦点を合わせて、全体の動作を概観します。
- リンク・フィールド解析関数
- コマンド生成関数
- レスポンス解析関数
6-2-1 初期化( iocInit )段階での処理
- リンク・フィールド解析関数が呼び出され、レコードのリンク・フィールド(
INP, OUTフィールド )の解析が行われます。
- 取得されたデバイスのアドレス情報は、DEVICE 構造体に納められます。
- 通常のコマンド/レスポンス型の通信の場合、ドライバ・サポートの中で、通信相手につき、一対の送信タスク/受信タスクが生成されます。
- イベント通知型の場合、メッセージを受信するサーバ・タスクが、TCP であれば送信者につき一つ、UDP であれば、受信ポートにつき一つ生成されます。
- 以上の処理は、iocInit コマンドがスタートアップ・スクリプトの中で実行される場合には、シェル・タスクのコンテキストで実行されることになります。
6-2-2 レコードのプロセスに伴う処理 (コマンド/レスポンス型の場合)
Initiation:
- レコードの SCAN フィールドの指定に応じて、
EPICS の General Purpose Task の何かが、レコードをプロセスします。
- このタスクから呼び出されたデバイス・サポートの関数は、送信要求をキューに入れて、送信タスクに通知します。
- 送信タスクは、コマンド生成関数を呼び出し、
DEVICE 構造体に納められた情報を基に、コマンドを送信バッファに構築します。
- 送信タスクは、watchdog timer をスタートしてから、コマンドの送信を行い、受信タスクからの受信通知、または watchdog timer
からのタイムアウト通知を待って休眠します。
Completion:
- やがて、受信タスクがデバイスからのレスポンスを受信します。
- 受信タスクは、watchdog timer が expire していないことを確認した後、レスポンス解析関数を呼び出して、レスポンスを検査します。
- レスポンスが期待されたものであり、データが正しく届けられた場合には、レコードのバッファに転送します。
- データを正しく受信したか否かに関わらず、受信タスクは EPICS の Callback Task にレコードのプロセスの非同期完成を依頼します。但し、
watchdog timer が expire していた場合には、この処理を watchdog timer
のハンドラに譲ります。
- 受信タスクは、送信タスクに受信の通知を行い、次のコマンドの送信を促します。watchdog timer が expire した場合には、そのハンドラがこれを代行します。
6-2-3 レコードのプロセスに伴う処理 (イベント通知型の場合)
- イベント通知型の場合、サーバ・タスクがデバイスからの通知を受信することで処理が起動されます。
- サーバ・タスクは、レコードの SCAN フィールドが "I/
O Intr"に指定されていることを確認した後、イベント解析関数を呼び出して、イベント・メッセージを検査し、イベントを待ち受けるレコードの有無を調べます。インプット型のレコードが見つかり、データが正しく届けられている場合には、レコードのバッファに転送します。アウトプット型レコードが見つかった場合には、レスポンス生成関数を呼び出して、応答データを送信します。レスポンス生成関数は、インプット型レコードへのメッセージに対して応答が必要な場合にも使うことができます。
- データの送受信が正常に行われたか否かに関わらず、サーバ・タスクは EPICS
の Task にレコードのプロセスを依頼します。
- サーバ・タスクは、次のイベント通知を待って休眠します。
6-3 ライブラリ関数と便利なマクロ
新たなデバイス・サポートの実装に役立つと思われる関数とマクロを列挙します。引数や戻り値の型などの詳細については、以下のファイルを参照して下さい。
- drvNetMpf.c ( .h )
- devNetDev.c ( .h )
以下に、まずデバイス・サポートの主要な機能の実装に使用する関数を列挙します。これらを核として、レコード型に特殊な処理などを含めたラッパー関数を用意することで、
DSET ( Device Support Entry Table ) メンバ関数を容易に作成することができます。
- netDevInit ( )
: init ( ) 関数の実装に使用します。
- netDevInitXxRecord : init_xx_record
( ) 関数の実装に使用します。
- netDevReadWriteXx ( ) : read_xx ( ) または
write_xx ( ) 関数の実装に使用します。
以下五つは、汎用性があると思われるサポート関数です。
- parseLinkPlcCommon ( ) :「4 リンクフィールドの書式」で述べた
PLC の場合の一般的な書式("@hostname(port_num):unit#type
:address")を解析する関数です。ポインタで渡された文字列を各構成要素に分解し、それらの先頭アドレスを結果引数として返します。構成要素の間の区切り記号は
NULL文字に置き換えられるため、返された構成要素の先頭アドレスを文字列へのポインタとして扱うことができます。
- toRecordVal ( ) : ドライバのバッファからレコードのバッファへオブジェクト・サイズやバイト順序の違いを考慮しながら転送する関数です。
- fromRecordVal ( ) : レコードのバッファからドライバのバッファへオブジェクト・サイズやバイト順序の違いを考慮しながら転送する関数です。
- netDevGetHostId ( ) : 与えられたストリングのホスト名(またはドット区切りの 10 進形式の
IP )から、32
ビット整数の IP
を結果引数として返します。結果引数として指定されたアドレス( sockaddr_in
構造体の然るべき位置を想定)に納められる値はネットワーク・バイト順序
に変換された値です。
- netDevGetSelfId ( ) : 引数なしで呼び出され、IOC の
IP を CPU Native
の 32 ビット整数の形で返します。
以下の三つの関数については、多少、背景説明が必要です。まず、基本的にドライバによるコマンド/レスポンスの送受信は、レコードのプロセスに伴うトランザクションです。しかし、デバイスの初期化時の処理などでは、デバイスへのパラメータ設定などのために、レコードのプロセスからは独立してコマンド/レスポンスの送受信が行えると便利な場合があります。このような目的で使用される内部的なトランザクションを行う関数を示します。
- netDevInitInternalIO ( ) : 内部的なトランザクションを行うための
Message Passing Facility を初期化します。
- netDevInternalIO ( ) : 内部的なトランザクションを行う関数です。
- netDevDeleteInternalIO ( ) : 内部的なトランザクションを行うための
Message Passing Facility を消去します。
以下の二つはマクロです。
- netDevInternalRead ( ) : netDevInternalIO ( ) をリード・オプションで実行します。
- netDevInternalWrite ( ) : netDevInternalIO ( ) をライト・オプションで実行します。
以下の六つのマクロは、初期化された PEER
構造体、
TRANSACTION 構造体から、パラメータを取得するために使用します。いずれも
TRANSACTION 構造体へのポインタを引数として渡します。
- GET_PEER_INET_ADDR ( t )
: 通信相手(デバイス)の IP を
CPU Native の
32 ビット整数の形で返します。
- GET_PEER_ID ( t )
: 通信相手(
PEER 構造体)の ID を返します。
- GET_PEER_DEVICE ( t )
: TRANSACTION 構造体中のDEVICE 構造体へのポインタを返します。
- GET_CLIENT_INET_ADDR ( t ) : イベント通知を行うクライアントの IP をネットワーク・バイト順序の 32 ビット整数の形で返します。
- GET_SERVER_PORT( t )
: サーバ・タスクがイベント・メッセージを待ち受け取るポート番号を返します。
- GET_SERVER_ID( t )
: TRANSACTION 構造体がリンクされている
SERVER構造体の ID を返します。
以上です。